package cn.fl.insurance.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cmm.comm.facade.upload.api.IUploadApiService;
import cmm.comm.facade.upload.dto.SysUlFilesRecDTO;
import cn.fl.preloan.dto.AddCompInfoRequest;
import cn.fl.preloan.dto.ModifyCompInfoRequest;
import cn.fl.preloan.enums.PreloanResultCodeEnum;
import cn.fl.preloan.insurance.IInsCompInfosService;
import cn.fl.system.constant.SysLogConstant;
import com.alibaba.fastjson.JSONObject;
import cn.fl.commons.result.ResponseData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

import cmm.comm.facade.framework.api.ISysDictionaryApiService;
import cmm.comm.facade.framework.dto.SysDictionaryDTO;
import cmm.mid.core.framework.page.KeyValueVO;
import cmm.mid.core.framework.page.Pager;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.cmm.base.framework.exception.BaseException;
import cn.cmm.base.framework.utils.BaseLogUtils;
import cn.cmm.base.framework.utils.CollectionUtils;
import cn.cmm.base.framework.utils.DecimalUtils;
import cn.cmm.base.framework.utils.StringUtils;
import cn.fl.capital.condition.CapFeeOutLogQueryCondition;
import cn.fl.capital.dto.CapFeeOutLogDTO;
import cn.fl.capital.service.ICapFeeOutLogApiService;
import cn.fl.framework.base.context.CurrentThreadContext;
import cn.fl.insurance.condition.InsCompChnPolQueryCondition;
import cn.fl.insurance.condition.InsCompInfoQueryCondition;
import cn.fl.insurance.constant.InsuranceConstant;
import cn.fl.insurance.dto.InsCompChnPolDTO;
import cn.fl.insurance.dto.InsCompInfoDTO;
import cn.fl.insurance.service.IInsCompChnPolApiService;
import cn.fl.insurance.service.IInsCompInfoApiService;
import cn.fl.insurance.service.IInsCompInfoService;
import cn.fl.insurance.transform.InsCompInfoVOTransform;
import cn.fl.insurance.vo.InsCompInfoVO;
import cn.fl.project.condition.PrjPrdDtlForInsQueryCondition;
import cn.fl.project.condition.PrjPrdPaySchDQueryCondition;
import cn.fl.project.dto.PrjPrdDtlForInsDTO;
import cn.fl.project.dto.PrjPrdPaySchDDTO;
import cn.fl.project.service.IPrjPrdPaySchDApiService;
import cn.fl.project.service.IProjectApiService;
import cn.fl.project.transform.PrjPrdDtlForInsVOTransform;
import cn.fl.project.vo.PrjPrdDtlForInsVO;
import cn.fl.system.service.ISysBkAccInfoService;
import fl.customer.facade.customer.api.ICustomerQueryApiService;

/**
 * @Description: 保险公司 客户端服务层接口实现
 * 业务层方法名称前缀：
 * 新增：add*
 * 删除：remove*
 * 修改：modify*
 * 批量：batch*
 * 查询对象：select* get*
 * 查询集合：search*
 */
@Service
public class InsCompInfoServiceImpl implements IInsCompInfoService {

    /**
     * 日志
     */
    private static final Logger logger = LoggerFactory.getLogger(InsCompInfoServiceImpl.class);

    /**
     * 自定义 API 暴露服务
     */
    @Autowired
    private IInsCompInfoApiService insCompInfoApiService;
    @Autowired
    private IInsCompChnPolApiService insCompChnPolApiService;
    @Autowired
    private ICustomerQueryApiService customerQueryApiService;

    /**
     * 数据字典 服务层BEAN
     */
    @Autowired
    private ISysDictionaryApiService sysDictionaryApiService;
    @Autowired
    private ISysBkAccInfoService sysBkAccInfoService;
    @Autowired
    private IProjectApiService projectApiService;
    @Autowired
    private IPrjPrdPaySchDApiService prjPrdPaySchDApiService;
    @Autowired
    private ICapFeeOutLogApiService capFeeOutLogApiService;

    @Autowired
    private IInsCompInfosService insCompInfosService;
    @Autowired
    private IUploadApiService uploadApiService;

    @Override
    public InsCompInfoVO selectById(Long id) throws BaseException {
        if (StringUtils.isEmpty(id)) return null;
        InsCompInfoDTO dto = this.insCompInfoApiService.selectInsCompInfoById(id, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
        return InsCompInfoVOTransform.toVO(dto);
    }

    @Override
    public Long add(InsCompInfoVO entity) throws BaseException {
        if (null == entity) return null;

        AddCompInfoRequest req = new AddCompInfoRequest();
        cn.fl.preloan.dto.InsCompInfoDTO dto = new cn.fl.preloan.dto.InsCompInfoDTO();
        BeanUtils.copyProperties(entity,dto);
        req.setDto(dto);
        ResponseData data = insCompInfosService.addInsCompInfo(req);
        if (!data.getCode().equals(PreloanResultCodeEnum.SUCCESS.getCode())) {
            return null;
        }
        //附件信息维护
        InsCompInfoDTO insCompInfoDTO = InsCompInfoVOTransform.toDTO(entity);
        List<SysUlFilesRecDTO> dtoList = insCompInfoDTO.getSysUlFilesRecDTOList();
        if(!CollectionUtils.isEmpty(dtoList)){
        for (SysUlFilesRecDTO sysUlFilesRecDTO : dtoList) {
            sysUlFilesRecDTO.setPkId(String.valueOf(dto.getId()));
            sysUlFilesRecDTO.setTabNm("INS_COMP_INFO");
            sysUlFilesRecDTO.setIsDel(BaseConstant.IS_YESNO_NO);
            this.uploadApiService.addSysUlFilesRec(sysUlFilesRecDTO);
             }
        }
        return dto.getId();
    }

    @Override
    public boolean removeByIds(List<Long> ids) throws BaseException {
        if (CollectionUtils.isEmpty(ids)) return false;
        return this.insCompInfoApiService.removeInsCompInfoByIds(ids, CurrentThreadContext.getCurrentUserId());
    }

    @Override
    public boolean modify(InsCompInfoVO entity) throws BaseException {
        if (null == entity) return false;
        ModifyCompInfoRequest req = new ModifyCompInfoRequest();
        cn.fl.preloan.dto.InsCompInfoDTO dto = new cn.fl.preloan.dto.InsCompInfoDTO();
        BeanUtils.copyProperties(entity,dto);
        req.setDto(dto);
        ResponseData data = insCompInfosService.mofifyInsCompInfo(req);
        if (!data.getCode().equals(PreloanResultCodeEnum.SUCCESS.getCode())) {
            return false;
        }
        //附件信息维护
        InsCompInfoDTO insCompInfoDTO = InsCompInfoVOTransform.toDTO(entity);
        List<SysUlFilesRecDTO> dtoList = insCompInfoDTO.getSysUlFilesRecDTOList();
        for (SysUlFilesRecDTO sysUlFilesRecDTO : dtoList) {
            sysUlFilesRecDTO.setPkId(String.valueOf(entity.getId()));
            sysUlFilesRecDTO.setTabNm("INS_COMP_INFO");
            sysUlFilesRecDTO.setIsDel(BaseConstant.IS_YESNO_NO);
            this.uploadApiService.addSysUlFilesRec(sysUlFilesRecDTO);
        }
        return true;
    }

    @Override
    public Pager searchListPage(Pager page) throws BaseException {
        if (null == page) {
            page = new Pager();
        } else {
            InsCompInfoQueryCondition qc = (InsCompInfoQueryCondition) page.getCondition();
            this.addDataFilter(qc);
        }
        page = this.insCompInfoApiService.searchInsCompInfoListPage(page, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
        if (CollectionUtils.isNotEmpty(page.getResultList())) {
            List<InsCompInfoDTO> dtoList = (List<InsCompInfoDTO>) page.getResultList();
            page.setResultList(InsCompInfoVOTransform.toVOList(dtoList));
        }
        return page;
    }

    @Override
    public List<InsCompInfoDTO> searchList(InsCompInfoQueryCondition condition) throws BaseException {
        this.addDataFilter(condition);
        return this.insCompInfoApiService.searchInsCompInfoList(condition);
    }

    /**
     * 添加数据过滤条件
     *
     * @param qc
     */
    public void addDataFilter(InsCompInfoQueryCondition qc) {
        if (qc != null && qc.getCompLvl() == 2) {//查询保险支公司 数据权限添加组织机构过滤
            qc.setUsrId(CurrentThreadContext.getCurrentUserId());
            qc.setSysCd(CurrentThreadContext.getCurrentSysCd());
        }
    }

    /**
     * 查询购买方式数据字典
     *
     * @return
     */
    public List<KeyValueVO> searchBuyWayCdList() throws BaseException {
        return this.sysDictionaryApiService.getKvList(InsuranceConstant.CODE_INS_BUY_WAY_CD, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
    }

    /**
     * 查询渠道类型数据字典
     *
     * @return
     */
    public List<KeyValueVO> searchChnCdList() throws BaseException {
        return this.sysDictionaryApiService.getKvList(InsuranceConstant.CODE_INS_COMP_CHN_CD, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
    }

    /**
     * 根据Code查询数据字典
     *
     * @return
     */
    public KeyValueVO searchDictListByCd(String grpCd, String chnCd) throws BaseException {
        SysDictionaryDTO dto = this.sysDictionaryApiService.getCode(CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd(), grpCd, chnCd);
        if (dto != null) {
            KeyValueVO vo = new KeyValueVO();
            vo.setKey(dto.getCode());
            vo.setValue(dto.getCodeNm());
            return vo;
        }
        return null;
    }

    /**
     * 查询开户行
     *
     * @return
     */
    public List<KeyValueVO> searchOpenBkInfo() throws BaseException {
        return this.sysDictionaryApiService.getKvList(InsuranceConstant.CODE_BK_CD, CurrentThreadContext.getCurrentSysCd(), CurrentThreadContext.getCurrentOrgCd());
        /*List<SysBkInfoVO> openBkList = this.sysBkAccInfoService.searchOpenBkInfo();
        List<KeyValueVO> keyValueVOList=new ArrayList<>();
        KeyValueVO keyValueVO=null;
        for(SysBkInfoVO vo:openBkList){
            keyValueVO=new KeyValueVO();
            keyValueVO.setKey(""+vo.getId());
            keyValueVO.setValue(vo.getBkNm());
            keyValueVOList.add(keyValueVO);
        }
        return keyValueVOList;*/
    }

    /**
     * 查询客户经理名下未投保的支付表产品信息 -非我司渠道保险支公司
     *
     * @param condition
     * @return
     * @throws BaseException
     */
    @Override
    public List<PrjPrdDtlForInsVO> selectPrjPrdList(InsCompInfoQueryCondition condition) throws BaseException {
        PrjPrdDtlForInsQueryCondition prjPrdDtlForInsQueryCondition = new PrjPrdDtlForInsQueryCondition();
        prjPrdDtlForInsQueryCondition.setCstMgrId(CurrentThreadContext.getCurrentUserId());//客户经理ID
        //prjPrdDtlForInsQueryCondition.setInsStsCd(InsuranceConstant.CODE_INS_PRD_STS_CD_10);//未投保
        List<PrjPrdDtlForInsDTO> dtlForInsDTOList = this.projectApiService.searchPrjPrdDtlListForIns(prjPrdDtlForInsQueryCondition);
        return PrjPrdDtlForInsVOTransform.toVOList(dtlForInsDTOList);
    }

    /**
     * 查询客户经理名下的支付表产品信息 -非我司渠道保险支公司
     *
     * @param page
     * @return
     * @throws BaseException
     */
    @Override
    public Pager selectPrjPrdListPage(Pager page) throws BaseException {
        if (null == page) {
            page = new Pager();
        }
        PrjPrdDtlForInsQueryCondition condition = null;
        if (null == page.getCondition()) {
            condition = new PrjPrdDtlForInsQueryCondition();
            page.setCondition(condition);
        } else {
            condition = (PrjPrdDtlForInsQueryCondition) page.getCondition();
        }
        page = this.projectApiService.searchPrjPrdDtlForInsListPage(page);
        if (CollectionUtils.isNotEmpty(page.getResultList())) {
            List<PrjPrdDtlForInsDTO> dtlForInsDTOList = (List<PrjPrdDtlForInsDTO>) page.getResultList();
            List<Long> paySchIdList = new ArrayList<>(dtlForInsDTOList.size());
            for (PrjPrdDtlForInsDTO dtlForInsDTO : dtlForInsDTOList) {
                paySchIdList.add(dtlForInsDTO.getPaySchId());
            }
            //支付表保证金费用项
            PrjPrdPaySchDQueryCondition paySchDQueryCondition = new PrjPrdPaySchDQueryCondition();
            paySchDQueryCondition.setPaySchIdList(paySchIdList);
            paySchDQueryCondition.setFeeTypCd(InsuranceConstant.CODE_FEE_TYP_CD_11);
            List<PrjPrdPaySchDDTO> paySchDDTOList = this.prjPrdPaySchDApiService.searchPrjPrdPaySchDList(paySchDQueryCondition);

            Map<Long, Long> depositMap = null;//每个支付表的保证金金额
            List<Long> dtlIdList = null;//支付表明细ID集合
            if (CollectionUtils.isNotEmpty(paySchDDTOList)) {
                depositMap = new HashMap<>(paySchDDTOList.size());
                dtlIdList = new ArrayList<>(dtlForInsDTOList.size());
                for (PrjPrdPaySchDDTO paySchDDTO : paySchDDTOList) {
                    depositMap.put(paySchDDTO.getPaySchId(), paySchDDTO.getFeeAmt().longValue());
                    dtlIdList.add(paySchDDTO.getId());
                }
            }
            //保证金是否有转出
            if (CollectionUtils.isNotEmpty(dtlIdList)) {
                CapFeeOutLogQueryCondition outLogQueryCondition = new CapFeeOutLogQueryCondition();
                outLogQueryCondition.setPaySchDIdList(dtlIdList);
                List<CapFeeOutLogDTO> outList = capFeeOutLogApiService.searchCapFeeOutLogList(outLogQueryCondition);
                for (CapFeeOutLogDTO outLogDTO : outList) {
                    if (depositMap.containsKey(outLogDTO.getPaySchId())) {
                        depositMap.put(outLogDTO.getPaySchId(), depositMap.get(outLogDTO.getPaySchId()) - outLogDTO.getOutAmt());
                    }
                }
            }
            //每个支付表能转出的保证金
            for (PrjPrdDtlForInsDTO dtlForInsDTO : dtlForInsDTOList) {
                if (depositMap != null && depositMap.containsKey(dtlForInsDTO.getPaySchId())) {
                    if (depositMap.get(dtlForInsDTO.getPaySchId()) > 0L) {
                        dtlForInsDTO.setDeposit(DecimalUtils.convertFenToYuan(depositMap.get(dtlForInsDTO.getPaySchId())));
                    }else{
                        dtlForInsDTO.setDeposit(0d);
                    }
                } else {
                    dtlForInsDTO.setDeposit(0d);
                }
            }

            page.setResultList(dtlForInsDTOList);
        }

        return page;
    }

    /**
     * 查询保险支公司
     *
     * @param condition
     * @return
     * @throws BaseException
     */
    @Override
    public Map<String, Object> selectInsSubComp(InsCompInfoQueryCondition condition) throws BaseException {
        Map<String, Object> result = null;
        if (null == condition) {
            condition = new InsCompInfoQueryCondition();
            condition.setCompStsCd(InsuranceConstant.CODE_INS_COMP_STS_CD_10);//保险公司状态：启用
        } else {
            if (StringUtils.isNotBlank(condition.getBuyWayCd())) {
                SysDictionaryDTO dictionaryDTO = this.sysDictionaryApiService.getCode(condition.getSysCd(), condition.getOrgCd(), InsuranceConstant.CODE_INS_BUY_WAY_CD, condition.getBuyWayCd());
                if (null != dictionaryDTO) {
                    condition.setChnCd(dictionaryDTO.getCodeAttr1());//渠道
                    condition.setBuyWayCd(null);

                    //判断是否返回一次性渠道支公司; 非我司渠道并且无特殊政策
                    if (InsuranceConstant.CODE_INS_COMP_CHN_CD_2.equals(dictionaryDTO.getCodeAttr1())
                            && StringUtils.isBlank(condition.getPlcSpePolCd())) {
                        BaseLogUtils.info(logger, "selectInsSubComp", "查询非我司渠道一次性保险支公司==" + JSON.toJSONString(condition));
                        //查询支付表号+产品明细ID已审批的一次性渠道政策
                        InsCompChnPolQueryCondition qc = new InsCompChnPolQueryCondition();
                        qc.setAudStsCd(InsuranceConstant.CODE_CHN_POL_AUD_STS_CD_30);
                        if (StringUtils.isBlank(condition.getPaySchNo())
                                || StringUtils.isBlank(condition.getInsTypCd())
                                || StringUtils.isBlank(condition.getPrdTypCd())) {
                            return null;
                        }
                        qc.setPaySchNo(condition.getPaySchNo());//支付表号
                        if (StringUtils.isNotEmpty(condition.getPrjPrdDtlId())) {
                            qc.setPrjPrdId(condition.getPrjPrdDtlId());//产品明细ID
                        }
                        qc.setIsValid(BaseConstant.IS_YESNO_YES);//有效
                        qc.setInsTypCd(condition.getInsTypCd());//险种
                        qc.setPrdTypCd(condition.getPrdTypCd());//保险产品类型
                        List<InsCompChnPolDTO> list = this.insCompChnPolApiService.searchInsCompChnPolList(qc);
                        BaseLogUtils.info(logger, "selectInsSubComp", "查询非我司渠道保险支公司政策==" + JSON.toJSONString(qc));
                        result = new HashMap<>(2);
                        if (CollectionUtils.isNotEmpty(list)) {
                            List<Long> compIdList = new ArrayList<>(list.size());
                            Map<Long,Long> compChnPolMap = new HashMap<>(16);
                            for(InsCompChnPolDTO chnPolDTO : list){
                                compIdList.add(chnPolDTO.getInsCompId());
                                compChnPolMap.put(chnPolDTO.getInsCompId(),chnPolDTO.getId());
                            }
                            //Long compId = list.get(0).getInsCompId();
                            InsCompInfoQueryCondition compInfoQueryCondition = new InsCompInfoQueryCondition();
                            compInfoQueryCondition.setIdList(compIdList);
                            compInfoQueryCondition.setCompLvl(2);
                            if(StringUtils.isNotBlank(condition.getRgnCyCd())){
                                compInfoQueryCondition.setRgnCyCd(condition.getRgnCyCd());
                            }
                            if(StringUtils.isNotBlank(condition.getRgnPrCd())) {
                                compInfoQueryCondition.setRgnPrCd(condition.getRgnPrCd());
                            }
                            List<InsCompInfoDTO> compList = this.insCompInfoApiService.searchInsCompInfoList(compInfoQueryCondition);
                            //InsCompInfoDTO comp = this.insCompInfoApiService.selectInsCompInfoById(compId);
                            if (CollectionUtils.isNotEmpty(compList)) {
                                InsCompInfoDTO comp = compList.get(0);
                                List<KeyValueVO> kvList = new ArrayList<>(1);
                                KeyValueVO kv = new KeyValueVO();
                                kv.setKey("" + comp.getId());
                                kv.setValue(comp.getCompNm());
                                kvList.add(kv);
                                result.put("subCompList", kvList);
                                if(compChnPolMap.containsKey(comp.getId())){
                                    result.put("chnPol", compChnPolMap.get(comp.getId()));
                                }
                            }else{
                                result.put("chnPol", list.get(0).getId());
                            }
                        }
                        return result;
                    }
                }
            }
            if (StringUtils.isBlank(condition.getCompStsCd())) {
                condition.setCompStsCd(InsuranceConstant.CODE_INS_COMP_STS_CD_10);//保险公司状态：启用
            }
        }

        BaseLogUtils.info(logger, "selectInsSubComp", "查询我司渠道保险支公司==" + JSON.toJSONString(condition));
        List<InsCompInfoDTO> insCompList = this.searchList(condition);
        if (CollectionUtils.isNotEmpty(insCompList)) {
            result = new HashMap<>(1);
            List<KeyValueVO> compList = new ArrayList<>(insCompList.size());
            KeyValueVO vo = null;
            for (InsCompInfoDTO dto : insCompList) {
                vo = new KeyValueVO();
                vo.setKey(dto.getId().toString());
                vo.setValue(dto.getCompNm());
                compList.add(vo);
            }
            result.put("subCompList", compList);
        }

        return result;
    }
}
